package com.yisoo.ubag.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yisoo.common.constant.RedisStringConstant;
import com.yisoo.common.to.CheckDeviceIsOpenTo;
import com.yisoo.common.to.RefreshBagStatusTo;
import com.yisoo.common.utils.R;
import com.yisoo.common.vo.OnlineVo;
import com.yisoo.common.vo.StatusEntityVo;
import com.yisoo.ubag.app.entity.PayEntity;
import com.yisoo.ubag.app.entity.PayLogEntity;
import com.yisoo.ubag.app.feign.IotFeignService;
import com.yisoo.ubag.app.feign.ProductFeignService;
import com.yisoo.ubag.app.service.PayLogService;
import com.yisoo.ubag.app.service.PayService;
import com.yisoo.common.utils.MyBeanUtils;
import com.yisoo.ubag.app.util.MyDateUtils;
import com.yisoo.ubag.app.vo.DevEntity;
import com.yisoo.ubag.app.vo.NewOrderVo;
import com.yisoo.ubag.app.vo.OrderDataVo;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yisoo.common.utils.PageUtils;
import com.yisoo.common.utils.Query;

import com.yisoo.ubag.app.dao.OrderDao;
import com.yisoo.ubag.app.entity.OrderEntity;
import com.yisoo.ubag.app.service.OrderService;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    IotFeignService iotFeignService;

    @Autowired
    ProductFeignService productFeignService;
    @Autowired
    ThreadPoolExecutor executorService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    PayService payService;
    @Autowired
    PayLogService payLogService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
        );

        return new PageUtils(page);
    }
    @Override
    public PageUtils queryPageByUid(Long uid, Map<String, Object> params) {
        QueryWrapper<OrderEntity> queryWrapper = new QueryWrapper<>();
        List<DevEntity> devByUid = productFeignService.getDevByUid(uid);
        for(DevEntity item:devByUid){
//            System.out.println(item);
            queryWrapper.eq("bag_id",item.getDevId()).or();
        }
        queryWrapper.eq("bag_id",-1);
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),queryWrapper
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPageByUidNofinish(Long uid, Map<String, Object> params) {
        QueryWrapper<OrderEntity> queryWrapper = new QueryWrapper<>();
        List<DevEntity> devByUid = productFeignService.getDevByUid(uid);
        for(DevEntity item:devByUid){
//            System.out.println(item);
            queryWrapper.eq("bag_id",item.getDevId()).or();
        }
       queryWrapper.eq("bag_id",-1).and(qw->queryWrapper.ne("order_status",4));
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),queryWrapper
        );

        return new PageUtils(page);
    }

    @Override
    public R getMoney(Long uid) {
        QueryWrapper<OrderEntity> queryWrapper;
        List<DevEntity> devByUid = productFeignService.getDevByUid(uid);
        List<String> payids = new ArrayList<>();
        List<OrderEntity> list;
        for(DevEntity item:devByUid){
            System.out.println(item);
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("bag_id",item.getDevId()).eq("order_status",4);
            list = baseMapper.selectList(queryWrapper);
            if(list!=null && list.size()>0){
                for (OrderEntity temp : list){
                    payids.add(temp.getPayId());
                }
            }
        }
        int today=0,total=0;
        for (String str : payids){
            PayLogEntity logEntity = payLogService.getById(str);
            int money = logEntity.getPayAccount().intValue();
            if(MyDateUtils.isNow(logEntity.getPayTime())){
                today+=money;
            }
            total+=money;
        }
        return R.ok().put("today",today).put("total",total);
    }

    //检查所有未完成订单
    @Override
    public List<OrderEntity> getOrderUnfinished(String uid){
        QueryWrapper<OrderEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("app_user_id",uid);
        List<OrderEntity> list = baseMapper.selectList(queryWrapper);
        if(list == null || list.size() == 0){
            return new ArrayList<OrderEntity>();
        }
        List<OrderEntity> entities = new ArrayList<>();
        for (OrderEntity item :list) {
            //未完成或者完成未付款
            if(item.getOrderStatus()==1 || item.getOrderStatus()==2){
                entities.add(item);
            }
        }
        return entities;
    }

    @Override
    public R autoOrder(String uid, String devSecret) {
        //本地信息检查
        //查询钱包中是否有钱
        if(payService.getBalanceData(uid).compareTo(new BigDecimal("0.00")) < 0){
            return R.error(501,"余额不足");
        }
        //查询订单中是否有未完成的
        List<OrderEntity> orderUnfinished = getOrderUnfinished(uid);
        if(orderUnfinished != null && orderUnfinished.size() > 0){
            //将未完成订单的数据补充到返回数据中
            OrderEntity orderEntity = orderUnfinished.get(0);
            NewOrderVo orderVo = new NewOrderVo();
            MyBeanUtils.copyProperties(orderEntity,orderVo);

            return R.error(502,"有未完成的订单").put("data",orderVo);
        }
        //远程设备检查
        CheckDeviceIsOpenTo res= iotFeignService.check(devSecret);
        if (res.getStatus() != CheckDeviceIsOpenTo.CheckDeviceStatus.DEVICE_OK){
            return R.error(503,res.getStatus().getMsg());
        }

        //到此检查完毕，应该创建订单了
        OrderEntity newOrder = new OrderEntity(
                null,
                uid,
                res.getBoxId(),
                new Date(),
                null,
                1,
                "状态未知",
                0,
                res.getBagId(),
                (long)-1);
        baseMapper.insert(newOrder);

        NewOrderVo newOrderVo = new NewOrderVo();
        MyBeanUtils.copyProperties(newOrder,newOrderVo);
        newOrderVo.setUuid(res.getUuid());
//        System.out.println(newOrderVo);

        return R.ok(res.getStatus().getMsg()).put("data", newOrderVo);
    }

    @Override
    public R refreshBagData(Long bagId) {
        //从product中查品牌和场景，查完存缓存，设置一个过期时间（修改引起的缓存同步问题不考虑）
        RefreshBagStatusTo statusTo1;
        if (stringRedisTemplate.hasKey(RedisStringConstant.DEV_BRAND_SCENE +bagId)){
            String s = stringRedisTemplate.opsForValue().get(RedisStringConstant.DEV_BRAND_SCENE + bagId);
            statusTo1 = JSON.parseObject(s, RefreshBagStatusTo.class);
//            System.out.println("1>>>"+s);
//            System.out.println(statusTo1);
            //如果一直延长缓存时间，那么管理员更新的数据将无法到达缓存
            //stringRedisTemplate.expire(RedisStringConstant.DEV_BRAND_SCENE + bagId,60*5 , TimeUnit.SECONDS);
        }else{
            statusTo1= productFeignService.getRel(bagId);
//            System.out.println("2>>>");
//            System.out.println(statusTo1);
            stringRedisTemplate.opsForValue().set(RedisStringConstant.DEV_BRAND_SCENE +bagId, JSONObject.toJSONString(statusTo1),60*5,TimeUnit.SECONDS);
        }
        //从iot中查状态：先查缓存，没有再远程调用接口
        RefreshBagStatusTo statusTo2 = new RefreshBagStatusTo();
        if (stringRedisTemplate.hasKey(RedisStringConstant.ONLINE_BAG + bagId)){

            String s = stringRedisTemplate.opsForValue().get(RedisStringConstant.ONLINE_BAG + bagId);
            OnlineVo temp = JSON.parseObject(s, OnlineVo.class);
            if (temp.getDeviceName()!=null){
                String ss = stringRedisTemplate.opsForValue().get(RedisStringConstant.DEV_PUB_STATUS + temp.getDeviceName());
                StatusEntityVo statusEntityVo = JSON.parseObject(ss, StatusEntityVo.class);
                MyBeanUtils.copyProperties(statusEntityVo,statusTo2);
                if(statusTo2.getBattery() == null){
                    System.out.println(">>>wenti:"+statusEntityVo.toString());
                }
            }else{
                statusTo2= iotFeignService.getBagStatusData(bagId);
            }

        }else{
            statusTo2= iotFeignService.getBagStatusData(bagId);
        }
//        MyBeanUtils.copyProperties(statusTo2,statusTo1);
        if (statusTo1 != null) {
            statusTo1.setBattery(statusTo2.getBattery());
        }else {
            System.out.println(statusTo2);
        }
        if (statusTo1 != null) {
            statusTo1.setHum(statusTo2.getHum());
            System.out.println(statusTo2);
        }
        if (statusTo1 != null) {
            statusTo1.setTem(statusTo2.getTem());
            System.out.println(statusTo2);
        }
        System.out.println(statusTo1);
        //电量总会出问题，应该是电路的问题没有解决好，这里为了显示不出问题，做一个修复
        double battery = statusTo1.getBattery();
        statusTo1.setBattery(battery-(int)battery+2.3);

        return  R.ok().put("data", statusTo1);
    }

    @Override
    public R getOrderStatus(String uid, Long bagId) {
        QueryWrapper<OrderEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("app_user_id",uid).eq("bag_id",bagId);
        List<OrderEntity> list = baseMapper.selectList(queryWrapper);
        OrderEntity orderEntity = null;
        for (OrderEntity item :list) {
            //未完成或者完成未付款
            if(item.getOrderStatus()==1 || item.getOrderStatus()==2){
                orderEntity = item;
                break;
            }
        }
        OrderDataVo orderDataVo = new OrderDataVo();
        orderDataVo.setOrderId(orderEntity.getOrderId());
        orderDataVo.setOrderStatus(orderEntity.getOrderStatus());
        //背包开关
        if(stringRedisTemplate.hasKey(RedisStringConstant.BAG_OPEN_OR_CLOSE+bagId)){
            String s = stringRedisTemplate.opsForValue().get(RedisStringConstant.BAG_OPEN_OR_CLOSE + bagId);
            orderDataVo.setBagSwitch(JSON.parseObject(s, Integer.class));
        }else{
            orderDataVo.setBagSwitch(0);
        }
        //无线充电开关
        if(stringRedisTemplate.hasKey(RedisStringConstant.BAG_WU_OPEN_OR_CLOSE+bagId)){
            String s = stringRedisTemplate.opsForValue().get(RedisStringConstant.BAG_WU_OPEN_OR_CLOSE + bagId);
            orderDataVo.setBagWuSwitch(JSON.parseObject(s, Integer.class));
        }else{
            orderDataVo.setBagWuSwitch(0);
        }

        return R.ok().put("data",orderDataVo);

    }

    @Override
    public R runOrderMapping(Long boxId,Long bagId, Integer control) {
        if(control == 101){
             iotFeignService.testMapping(boxId,control);
            iotFeignService.testMapping(bagId,201);
        }else if (control == 102){
            iotFeignService.testMapping(boxId,control);
            iotFeignService.testMapping(bagId,202);
        }else{
            iotFeignService.testMapping(bagId,control);
        }
        return R.ok();
    }

    @Override
    public R ok(String uid, Long bagId) {
        QueryWrapper<OrderEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("app_user_id",uid).eq("bag_id",bagId);
        List<OrderEntity> list = baseMapper.selectList(queryWrapper);
        OrderEntity orderEntity = null;
        for (OrderEntity item :list) {
            //未完成或者完成未付款
            if(item.getOrderStatus()==1 || item.getOrderStatus()==2){
                orderEntity = item;
                break;
            }
        }
//        assert orderEntity != null;
        PayLogEntity payLogEntity = new PayLogEntity(UUID.randomUUID().toString(),uid,new BigDecimal("3.00"),new Date(),orderEntity.getOrderId());
        payLogService.save(payLogEntity);
        PayEntity payEntity = payService.getById(uid);
        payEntity.setMoney(payEntity.getMoney().subtract(new BigDecimal("3.00")));
        payService.updateById(payEntity);

        orderEntity.setOrderStatus(4);
        orderEntity.setEndTime(new Date());
        orderEntity.setPayId(payLogEntity.getPayId());
        baseMapper.updateById(orderEntity);
        return R.ok();
    }




}